using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Practices.ServiceLocation;

namespace PrismNavigationFramework.Navigation
{
    public class PrismNavigation : ItemsControl, INotifyPropertyChanged
    {
        private static int _instances;

        private static bool IsDesignTime
        {
            get
            {
                return DesignerProperties.IsInDesignTool; 
            }
        }

        private IPrismViewLoadingService _prismViewLoadingService
        {
            get
            {
                if (IsDesignTime)
                {
                    return null;
                }
                return ServiceLocator.Current.GetInstance<IPrismViewLoadingService>();
            }            
        }

        private IPrismNavigationConfiguration _prismNavigationConfiguration
        {
            get
            {
                if (IsDesignTime)
                {
                    return null;
                }
                return ServiceLocator.Current.GetInstance<IPrismNavigationConfiguration>();
            }
        }

        public PrismNavigation()
        {
            this.Width = 0;
            this.Height = 0;

            _instances++;

            if (_instances > 1)
            {
                throw new Exception("You should not have more than one PrismNavigation instance in your application.");
            }

            if (IsDesignTime)
            {
                return;
            }

            this.Loaded += PrismNavigationLoaded;
/*            this._navigationFrameAdaptersRegistrationService.NewSilverlightNavigationFrameAdapterCreated +=
                this.OnNewFrameAdapterCreated;*/
        }

/*        private void OnNewFrameAdapterCreated(object sender, NewSilverlightNavigationFrameAdapterCreatedEventArgs e)
        {
            var adapter = e.Adapter;
            var adapterNameLower = adapter.Name.ToLower();
            if (adapterNameLower == this.MainRegionName.ToLower())
            {
                adapter.IsMainRegion = true;
            }

            var alreadyHaveAdapter = this.Items.OfType<ContentControl>().Any(itemAsContentControl => itemAsContentControl.Name.ToLower() == adapterNameLower);

            if (!alreadyHaveAdapter)
            {
                adapter.OnNavigate = OnAdapterNavigate;
                this.Items.Add(adapter);
            }
        }*/

        public string DefaultApplicationUrl { get; set; }

/*        private void OnAdapterNavigate(SilverlightNavigationFrameToPrismRegionAdapter adapter, Uri source)
        {
            if (adapter.IsMainRegion)
            {
                Application.Current.Host.NavigationState = source.OriginalString;
            }
            else
            {
                this.LoadUrlToRegion(source.OriginalString, adapter.Name);
            }
        }*/

        void PrismNavigationLoaded(object sender, RoutedEventArgs e)
        {
            Application.Current.Host.NavigationStateChanged += HostNavigationStateChanged;

            if (string.IsNullOrEmpty(Application.Current.Host.NavigationState))
            {
                if (!string.IsNullOrEmpty(this.DefaultApplicationUrl))
                {
                    Application.Current.Host.NavigationState = DefaultApplicationUrl;
                }
                else
                {
                    Application.Current.Host.NavigationState = string.Format("/{0}/{1}",
                                                                             this._prismNavigationConfiguration.
                                                                                 DefaultModuleName,
                                                                             this._prismNavigationConfiguration.
                                                                                 DefaultViewName);
                }
            }
            else if (Application.Current.Host.NavigationState != this._prismViewLoadingService.CurrentMainRegionUrl)
            {
                // this is a hack to force our view to be loaded if user reloads page in browser
                this.NavigationStateChanged(Application.Current.Host.NavigationState);
            }
        }

        public string MainRegionName
        {
            get
            {
                return this._prismNavigationConfiguration.MainRegionName;
            }

            set
            {
                if (IsDesignTime)
                {
                    return;
                }

                this._prismNavigationConfiguration.MainRegionName = value;
            }
        }

        private void NavigationStateChanged(string newUrl)
        {
            this.LoadUrlToRegion(newUrl, this.MainRegionName);
        }

        private void LoadUrlToRegion(string newUrl, string regionName)
        {
            this._prismViewLoadingService.LoadUrlToRegion(newUrl, regionName);
        }

        void HostNavigationStateChanged(object sender, System.Windows.Interop.NavigationStateChangedEventArgs e)
        {
            this.LoadUrlToRegion(e.NewNavigationState, this.MainRegionName);
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void RaiseNotifyPropertyChanged(string propertyName)
        {
            var handler = this.PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }         
        }
    }
}